package com.bxj.mybatis.generator.plugin;

import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.NullProgressCallback;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MapperPlugin extends PluginAdapter {

    private static final String DEFAULT_DAO_SUPER_CLASS = "com.dfz.base.BaseMapper";
    private static final String DEFAULT_EXPAND_DAO_SUPER_CLASS = "com.dfz.base.BaseExpandMapper";
    private String mapperProject;
    private String mapperPackage;

    private String daoSuperClass;

    // 扩展
    private String expandDaoTargetPackage;
    private String expandDaoSuperClass;
    String xmlProject;


    private ShellCallback shellCallback = null;

    public MapperPlugin() {
        shellCallback = new DefaultShellCallback(false);
    }


    /**
     * 验证参数是否有效
     *
     * @param warnings
     * @return
     */
    public boolean validate(List<String> warnings) {
        mapperProject = properties.getProperty("mapperProject");
        if (StringUtils.isEmpty(mapperProject))
            return false;
        mapperPackage = properties.getProperty("mapperPackage");
        if (StringUtils.isEmpty(mapperPackage))
            return false;

        xmlProject = properties.getProperty("xmlProject");
        if (StringUtils.isEmpty(xmlProject))
            return false;

        daoSuperClass = properties.getProperty("daoSuperClass");
        if (StringUtils.isEmpty(daoSuperClass)) {
            daoSuperClass = DEFAULT_DAO_SUPER_CLASS;
        }
        expandDaoTargetPackage = properties.getProperty("expandTargetPackage");
        expandDaoSuperClass = properties.getProperty("expandDaoSuperClass");
        if (StringUtils.isEmpty(expandDaoSuperClass)) {
            expandDaoSuperClass = DEFAULT_EXPAND_DAO_SUPER_CLASS;
        }
        return true;
    }

    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {

//        if (generatorRule == GeneratorRule.Slave) {
//            XmlElement select = new XmlElement("select");
//            select.addAttribute(new Attribute("id", "selectAll"));
//            select.addAttribute(new Attribute("resultMap", "BaseResultMap"));
//            select.addAttribute(new Attribute("parameterType", introspectedTable.getBaseRecordType()));
//            select.addElement(new TextElement(" select * from " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
//            XmlElement parentElement = document.getRootElement();
//            parentElement.addElement(select);
//
//
//            XmlElement paginationElement = new XmlElement("sql");
//            paginationElement.addAttribute(new Attribute("id", "MySql_Pagination"));
//            XmlElement limitElement = new XmlElement("if");
//            limitElement.addAttribute(new Attribute("test", "limit[0] != -1 &amp;&amp; limit[1] != -1"));
//            limitElement.addElement(new TextElement("limit #{limitValue1}, #{limitValue2}"));
//            paginationElement.addElement(limitElement);
//            parentElement.addElement(paginationElement);
//        }
//        return super.sqlMapDocumentGenerated(document, introspectedTable);

        return true;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        if (!MybatisUtils.checkReplaceIfExists(introspectedTable, mapperProject, topLevelClass.getType().getPackageName(), topLevelClass.getType().getShortName() + ".java")) {
            return false;
        }
        return super.modelBaseRecordClassGenerated(topLevelClass, introspectedTable);
    }

    @Override
    public List<GeneratedXmlFile> contextGenerateAdditionalXmlFiles(IntrospectedTable introspectedTable) {
        List<GeneratedXmlFile> answer = new ArrayList<GeneratedXmlFile>();
        for (GeneratorRule generatorRule : GeneratorRule.values()) {
            FullyQualifiedTable table = introspectedTable.getFullyQualifiedTable();

            HaXMLMapperGenerator xmlMapperGenerator = new HaXMLMapperGenerator();
            xmlMapperGenerator.setIntrospectedTable(introspectedTable);
            xmlMapperGenerator.setProgressCallback(new NullProgressCallback());
            xmlMapperGenerator.setContext(this.context);
            xmlMapperGenerator.setGeneratorRule(generatorRule);
            xmlMapperGenerator.setNamespace(mapperPackage + "." + generatorRule.getName() + "." + table.getDomainObjectName() + generatorRule.toString() + "Mapper");


            Document document = xmlMapperGenerator.getDocument();

            if (!MybatisUtils.checkReplaceIfExists(introspectedTable, xmlProject, generatorRule.getName(), table.getDomainObjectName() + generatorRule.toString() + "Mapper.xml")) {
                continue;
            }
            new File(xmlProject + "/" + generatorRule.getName() + "/" + table.getDomainObjectName() + generatorRule.toString() + "Mapper.xml").delete();
            GeneratedXmlFile gxf = new GeneratedXmlFile(document,
                    table.getDomainObjectName() + generatorRule.toString() + "Mapper.xml", generatorRule.getName(),
                    xmlProject,
                    true, context.getXmlFormatter());
            if (context.getPlugins().sqlMapGenerated(gxf, introspectedTable)) {
                answer.add(gxf);
            }
        }
        return answer;
    }

    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        JavaFormatter javaFormatter = context.getJavaFormatter();
        List<GeneratedJavaFile> mapperJavaFiles = new ArrayList<GeneratedJavaFile>();
        for (GeneratorRule generatorRule : GeneratorRule.values()) {
            for (GeneratedJavaFile javaFile : introspectedTable.getGeneratedJavaFiles()) {
                CompilationUnit unit = javaFile.getCompilationUnit();
                FullyQualifiedJavaType baseModelJavaType = unit.getType();

                String shortName = baseModelJavaType.getShortName();
                GeneratedJavaFile mapperJavafile = null;
                if (shortName.endsWith("Mapper")) { // 扩展Mapper
                    if (!StringUtils.isEmpty(expandDaoTargetPackage)) {
                        Interface mapperInterface = new Interface(
                                expandDaoTargetPackage + "." + shortName.replace("Mapper", "ExpandMapper"));
                        if (!MybatisUtils.checkReplaceIfExists(introspectedTable, mapperProject, expandDaoTargetPackage, shortName.replace("Mapper", "ExpandMapper") + ".java"))
                            return mapperJavaFiles;
                        mapperInterface.setVisibility(JavaVisibility.PUBLIC);
                        mapperInterface.addJavaDocLine("/**");
                        mapperInterface.addJavaDocLine(" * " + shortName + "扩展");
                        mapperInterface.addJavaDocLine(" */");

                        FullyQualifiedJavaType daoSuperType = new FullyQualifiedJavaType(expandDaoSuperClass);
                        mapperInterface.addImportedType(daoSuperType);
                        mapperInterface.addSuperInterface(daoSuperType);

                        mapperJavafile = new GeneratedJavaFile(mapperInterface, mapperProject, javaFormatter);
                        try {
                            File mapperDir = shellCallback.getDirectory(mapperProject, mapperPackage);
                            File mapperFile = new File(mapperDir, mapperJavafile.getFileName());
                            // 文件不存在
//                        if (!mapperFile.exists()) {
                            mapperJavaFiles.add(mapperJavafile);
//                        }
                        } catch (ShellException e) {
                            e.printStackTrace();
                        }
                    }
                } else if (!shortName.endsWith("Example")) { // CRUD Mapper
                    String mapperType = mapperPackage + "." + generatorRule.getName() + "." + shortName + generatorRule.toString() + "Mapper";

                    if (!MybatisUtils.checkReplaceIfExists(introspectedTable, mapperProject, mapperPackage + "." + generatorRule.getName(), shortName + generatorRule.toString() + "Mapper.java"))
                        return mapperJavaFiles;

                    HaJavaMapperGenerator javaMapperGenerator = new HaJavaMapperGenerator(true);
                    javaMapperGenerator.setIntrospectedTable(introspectedTable);
                    javaMapperGenerator.setProgressCallback(new NullProgressCallback());
                    javaMapperGenerator.setContext(this.context);
                    javaMapperGenerator.setGeneratorRule(generatorRule);
                    introspectedTable.setMyBatis3JavaMapperType(mapperType);
                    introspectedTable
                            .setAttribute(PropertyRegistry.ANY_ROOT_INTERFACE, "Object");
                    for (CompilationUnit compilationUnit : javaMapperGenerator.getCompilationUnits()) {
                        mapperJavafile = new GeneratedJavaFile(compilationUnit, mapperProject, javaFormatter);
                        mapperJavaFiles.add(mapperJavafile);
                    }
                    //selectByPrimaryKey函数
//                    Method method = new Method();
//                    method.setName("selectByPrimaryKey");
//
//                    for (IntrospectedColumn column : introspectedTable.getPrimaryKeyColumns()) {
//                        method.addParameter(new Parameter(column.getFullyQualifiedJavaType(), column.getJavaProperty(), false));
//                    }
//                    method.setReturnType(objectType);
//                    mapperInterface.addMethod(method);
//
//                    mapperJavafile = new GeneratedJavaFile(mapperInterface, mapperProject, javaFormatter);
//                    mapperJavaFiles.add(mapperJavafile);
                    //18002137963
                }
            }
        }
        return mapperJavaFiles;
    }

    @Override
    public void initialized(IntrospectedTable introspectedTable) {
        super.initialized(introspectedTable);

        introspectedTable.setCountByExampleStatementId(MybatisUtils.getTableProperties(introspectedTable, "countByExampleStatementId", "countByExample")); //$NON-NLS-1$
        introspectedTable.setDeleteByExampleStatementId(MybatisUtils.getTableProperties(introspectedTable, "deleteByExampleStatementId", "deleteByExample")); //$NON-NLS-1$
        introspectedTable.setDeleteByPrimaryKeyStatementId(MybatisUtils.getTableProperties(introspectedTable, "deleteByPrimaryKeyStatementId", "deleteById")); //$NON-NLS-1$
        introspectedTable.setInsertStatementId(MybatisUtils.getTableProperties(introspectedTable, "insertStatementId", "insert")); //$NON-NLS-1$
        introspectedTable.setInsertSelectiveStatementId(MybatisUtils.getTableProperties(introspectedTable, "insertSelectiveStatementId", "insertSelective")); //$NON-NLS-1$
        introspectedTable.setSelectAllStatementId(MybatisUtils.getTableProperties(introspectedTable, "selectAllStatementId", "selectAll")); //$NON-NLS-1$
        introspectedTable.setSelectByExampleStatementId(MybatisUtils.getTableProperties(introspectedTable, "selectByExampleStatementId", "selectById")); //$NON-NLS-1$
        introspectedTable.setSelectByExampleWithBLOBsStatementId(MybatisUtils.getTableProperties(introspectedTable, "selectByExampleWithBLOBsStatementId", "selectByExampleWithBLOBs")); //$NON-NLS-1$
        introspectedTable.setSelectByPrimaryKeyStatementId(MybatisUtils.getTableProperties(introspectedTable, "selectByPrimaryKeyStatementId", "selectById")); //$NON-NLS-1$
        introspectedTable.setUpdateByExampleStatementId(MybatisUtils.getTableProperties(introspectedTable, "updateByExampleStatementId", "updateById")); //$NON-NLS-1$
        introspectedTable.setUpdateByExampleSelectiveStatementId(MybatisUtils.getTableProperties(introspectedTable, "updateByExampleSelectiveStatementId", "updateByExampleSelective")); //$NON-NLS-1$
        introspectedTable.setUpdateByExampleWithBLOBsStatementId(MybatisUtils.getTableProperties(introspectedTable, "updateByExampleWithBLOBsStatementId", "updateByExampleWithBLOBs")); //$NON-NLS-1$
        introspectedTable.setUpdateByPrimaryKeyStatementId(MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeyStatementId", "updateById")); //$NON-NLS-1$
        introspectedTable.setUpdateByPrimaryKeySelectiveStatementId(MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeySelectiveStatementId", "updateSelectiveById")); //$NON-NLS-1$
        introspectedTable.setUpdateByPrimaryKeyWithBLOBsStatementId(MybatisUtils.getTableProperties(introspectedTable, "updateByPrimaryKeyWithBLOBsStatementId", "updateByPrimaryKeyWithBLOBs")); //$NON-NLS-1$
        introspectedTable.setBaseResultMapId("BaseResultMap"); //$NON-NLS-1$
        introspectedTable.setResultMapWithBLOBsId("ResultMapWithBLOBs"); //$NON-NLS-1$
        introspectedTable.setExampleWhereClauseId("Example_Where_Clause"); //$NON-NLS-1$
        introspectedTable.setBaseColumnListId("Base_Column_List"); //$NON-NLS-1$
        introspectedTable.setBlobColumnListId("Blob_Column_List"); //$NON-NLS-1$
        introspectedTable.setMyBatis3UpdateByExampleWhereClauseId("Update_By_Example_Where_Clause"); //$NON-NLS-1$
    }
}